#include "chatserver.h"

#include <qbluetoothserver.h>
#include <qbluetoothsocket.h>
#include <qbluetoothlocaldevice.h>
static const QLatin1String
serviceUuid("e8e10f95-1a70-4b27-9ccf-02010264e9c8");
ChatServer::ChatServer(QWidget *parent) :
    QWidget(parent)
{

}

ChatServer::~ChatServer()
{
    stopServer();
}
void ChatServer::startServer(const QBluetoothAddress& localAdapter)
{
    if (rfcommServer)
        return;

    // 创建RFCOMM服务器
    rfcommServer = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this);
    connect(rfcommServer, SIGNAL(newConnection()), this, SLOT(clientConnected()));

    // 监听指定适配器
    bool result = rfcommServer->listen(localAdapter);
    if (!result) {
        qWarning() << "Cannot bind chat server to" << localAdapter.toString();
        return;
    }

    // 配置服务信息
    QBluetoothServiceInfo::Sequence classId;
    classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
    serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, classId);

    classId.prepend(QVariant::fromValue(QBluetoothUuid(serviceUuid)));
    serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
    serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, classId);

    serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, tr("Bt Chat Server"));
    serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription, tr("Example bluetooth chat server"));
    serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, tr("qt-project.org"));
    serviceInfo.setServiceUuid(QBluetoothUuid(serviceUuid));

    // 设置浏览组
    QBluetoothServiceInfo::Sequence publicBrowse;
    publicBrowse << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
    serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, publicBrowse);

    // 设置协议描述符
    QBluetoothServiceInfo::Sequence protocolDescriptorList;
    QBluetoothServiceInfo::Sequence protocol;
    protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap));
    protocolDescriptorList.append(QVariant::fromValue(protocol));

    protocol.clear();
    protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
             << QVariant::fromValue(quint8(rfcommServer->serverPort()));
    protocolDescriptorList.append(QVariant::fromValue(protocol));

    serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList);

    // 注册服务
    serviceInfo.registerService(localAdapter);
}

void ChatServer::stopServer()
{
    // 注销服务
    serviceInfo.unregisterService();

    // 关闭所有客户端套接字
    qDeleteAll(clientSockets);
    clientSockets.clear();
    socketsPeername.clear();

    // 关闭服务器
    delete rfcommServer;
    rfcommServer = nullptr;
}

void ChatServer::disconnect()
{
    qDebug() << "Going to disconnect in server";

    foreach (QBluetoothSocket *socket, clientSockets) {
        qDebug() << "sending data in server!";
        socket->close();
    }
}

void ChatServer::sendMessage(const QString &message)
{
    qDebug() << "Going to send message in server: " << message;
    QByteArray text = message.toUtf8() + '\n';

    foreach (QBluetoothSocket *socket, clientSockets) {
        qDebug() << "sending data in server!";
        socket->write(text);
    }
    qDebug() << "server sending done!";
}

void ChatServer::clientConnected()
{
    qDebug() << "clientConnected";

    QBluetoothSocket *socket = rfcommServer->nextPendingConnection();
    if (!socket)
        return;

    connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
    connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));

    clientSockets.append(socket);
    socketsPeername.append(socket->peerName());

    emit clientConnected(socket->peerName());
}

void ChatServer::clientDisconnected()
{
    QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender());
    if (!socket)
        return;

    if (clientSockets.count() != 0) {
        QString peerName;

        if (socket->peerName().isEmpty())
            peerName = socketsPeername.at(clientSockets.indexOf(socket));
        else
            peerName = socket->peerName();

        emit clientDisconnected(peerName);

        clientSockets.removeOne(socket);
        socketsPeername.removeOne(peerName);
    }

    socket->deleteLater();
}

void ChatServer::readSocket()
{
    QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender());
    if (!socket)
        return;

    while (socket->bytesAvailable()) {
        QByteArray line = socket->readLine().trimmed();
        qDebug() << QString::fromUtf8(line.constData(), line.length());

        emit messageReceived(socket->peerName(),
                           QString::fromUtf8(line.constData(), line.length()));

        qDebug() << QString::fromUtf8(line.constData(), line.length());
    }
}

